package com.xishu.controller;

import com.xishu.annotation.dao.CustomerNotModify;
import com.xishu.annotation.valid.MethodValidator;
import com.xishu.aop.Validator;
import com.xishu.bo.*;
import com.xishu.bo.customer.RandomCode;
import com.xishu.bo.customer.RandomLogin;
import com.xishu.client.CustomerEmailClient;
import com.xishu.client.EmailClient;
import com.xishu.client.sms.IsmsClient;
import com.xishu.client.sms.SmsFactory;
import com.xishu.config.Config;
import com.xishu.entity.Company;
import com.xishu.entity.User;
import com.xishu.entity.customer.*;
import com.xishu.entity.order.Order;
import com.xishu.entity.shop.DiscountTicket;
import com.xishu.entity.shop.Shop;
import com.xishu.exception.ResponseStatusException;
import com.xishu.response.ResponseData;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.service.order.base.OrderService;
import com.xishu.task.ZeroTimeSystemTask;
import com.xishu.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.validator.routines.EmailValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static com.xishu.config.Constant.*;
import static com.xishu.response.ResponseStatus.*;
import static com.xishu.service.CustomerService.PHONE_AREA_CODE;

@Api(description = "会员系统")
@RestController
public class CustomerController implements Tools {
    private static Logger logger = LoggerFactory.getLogger(CustomerController.class);
    private Config config = Config.getInstance();

    private CustomerService customerService = CustomerService.getInstance();
    private CompanyService companyService = CompanyService.getInstance();
    private CommonService commonService = CommonService.getInstance();
    private ShopService shopService = ShopService.getInstance();

    @ApiOperation(value = "邮件预览")
    @PutMapping(value = ("/vip/renew/template/preview"), produces = ("application/json;charset=UTF-8"))
    public ResponseData testEmail(@RequestBody VipRenewEmailTemplate vipRenewEmailTemplate) throws Exception {
        String title = getTitle(vipRenewEmailTemplate);
        String content = getContent(vipRenewEmailTemplate);
        String preViewEmail = vipRenewEmailTemplate.getPreViewEmail();
        Long companyId = vipRenewEmailTemplate.getCompanyId();
        VerifyUtil.isEmpty(title, content, preViewEmail);

        Company company = companyService.findCompanyById(companyId);
        boolean own = companyService.ownCompany(companyId);
        VerifyUtil.verify(() -> own);

        //判断邮件是否还足够
        Optional<Quota> quotaOptional = customerService.findQuotaOrCreate(companyId);
        VerifyUtil.verify(() -> quotaOptional.isPresent());

        Quota quota = quotaOptional.get();
        VerifyUtil.verify(() -> getInt(quota.getUnPlanEmailCanUsed()) > 0, EMAIL_NOT_ENOUGH);
        Integer emailCanUsed = quota.getUnPlanEmailCanUsed();
        quota.setUnPlanEmailCanUsed(emailCanUsed - 1);
        quota.setUnPlanEmailUsed(getInt(quota.getUnPlanEmailUsed()) + 1);
        commonService.save(quota);

        String sendNameInEmail = company.getCompanyConfig().getSendNameInEmail();
        CustomerEmailClient.getInstance().sendEmail(sendNameInEmail, preViewEmail, title, content);
        customerService.addEmailSendHistory(companyId, false);

        return ResponseData.emptyResponse();
    }

    private String getContent(VipRenewEmailTemplate vipRenewEmailTemplate) {
        if (isNotEmpty(vipRenewEmailTemplate.getContent())) {
            return vipRenewEmailTemplate.getContent();
        }

        return vipRenewEmailTemplate.getEmailContent();

    }

    private String getTitle(VipRenewEmailTemplate vipRenewEmailTemplate) {
        if (isNotEmpty(vipRenewEmailTemplate.getTitle())) {

            return vipRenewEmailTemplate.getTitle();
        }

        return vipRenewEmailTemplate.getEmailTitle();
    }

    @ApiOperation(value = "通过电话号码获取验证码")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/phone/random/code"), produces = ("application/json;charset=UTF-8"))
    public ResponseData getPhoneRandomCode(@RequestBody PhoneBo phoneBo) throws Exception {
        String phone = phoneBo.getPhone();
        String areaCode = phoneBo.getAreaCode();
        VerifyUtil.isEmpty(phoneBo.getPhone(), areaCode);

        //如果是登录的验证码，需要判断账号是否存在
        if (phoneBo.isLogin()) {
            Customer customer = customerService.findCustomerByPhone(phone, areaCode, phoneBo.getCompanyId());
            VerifyUtil.verify(() -> customer != null, CUSTOMER_NOT_EXITS);
            VerifyUtil.verify(() -> customer != null, CUSTOMER_NOT_EXITS);
            VerifyUtil.verify(() -> getInt(customer.getStatus()) == 0, CUSTOMER_FROZEN);
        }

        Long companyId = phoneBo.getCompanyId();
        VerifyUtil.verify(() -> companyId != null);
        Optional<Quota> quotaOptional = customerService.findQuotaOrCreate(companyId);

        //这里应该一定会有配额的
        VerifyUtil.verify(() -> quotaOptional.isPresent());
        Quota quota = quotaOptional.get();
        Integer smsCanUsed = getInt(quota.getUnPlanSmsCanUsed());
        VerifyUtil.verify(() -> smsCanUsed > 0, SMS_NOT_ENOUGH);
        //修改配额
        quota.setUnPlanSmsCanUsed(smsCanUsed - 1);
        //修改历史发送条数记录
        quota.setUnPlanSmsUsed(getInt(quota.getUnPlanSmsUsed()) + 1);
        commonService.save(quota);

        //如果配额小于等于0，那么将开关关闭
        if (quota.getUnPlanSmsCanUsed() <= 0) {
            Company company = companyService.findCompanyById(companyId);
            company.getCompanyConfig().setPhoneToken(false);
            commonService.save(company);

            //判断通知是否已经发送过了，如果已经发送过了，则不再发送
            sendUsedOutTask(company, false);
        }

        String numberCode = customerService.generateRandom(phone);
        String smsContent = customerService.smsRandomCodeContent(areaCode, numberCode);

        IsmsClient smsClient = SmsFactory.getInstance().createClient(areaCode);
        smsClient.send(areaCode, phone, smsContent);

        //添加日志，以做统计
        customerService.addSmsSendHistory(companyId, false, 1);

        //电话号码，那么写下区号
        JRedisUtil.setKV(PHONE_AREA_CODE + phone, areaCode);

        if (config.isAliyun()) {
            return commonService.createResponse(numberCode);
        } else {
            return ResponseData.emptyResponse();
        }
    }

    @ApiOperation(value = "通过邮箱获取验证码，需要带companyId")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/email/random/code"), produces = ("application/json;charset=UTF-8"))
    public ResponseData getEmailRandomCode(@RequestBody Customer customer) throws Exception {
        String email = customer.getEmail();
        Long companyId = customer.getCompanyId();
        VerifyUtil.isEmpty(email);
        VerifyUtil.verify(() -> companyId != 0);

        VerifyUtil.verify(() -> EmailValidator.getInstance().isValid(email), ACCOUNT_MUST_BE_EMAIL);
        Company company = companyService.findCompanyById(companyId);

        String numberCode = customerService.generateRandom(email);
        String emailContent = customerService.emailRandomCodeContent(numberCode);
        String emailTitle = customerService.randomCodeEmailTitle(numberCode);

        //判断配额
        Optional<Quota> quotaOptional = customerService.findQuotaOrCreate(companyId);
        VerifyUtil.verify(() -> quotaOptional.isPresent());
        Quota quota = quotaOptional.get();
        Integer emailCanUsed = getInt(quota.getUnPlanEmailCanUsed());
        VerifyUtil.verify(() -> emailCanUsed > 0, EMAIL_NOT_ENOUGH);
        //更新配额
        quota.setUnPlanEmailCanUsed(quota.getUnPlanEmailCanUsed() - 1);
        quota.setUnPlanEmailUsed(getInt(quota.getUnPlanEmailUsed()) + 1);
        commonService.save(quota);

        //处理开关
        if (quota.getUnPlanEmailCanUsed() <= 0) {
            company.getCompanyConfig().setEmailToken(false);
            commonService.save(company);

            sendUsedOutTask(company, true);
        }

        CustomerEmailClient.getInstance().sendEmail(company.getCompanyConfig().getSendNameInEmail(), email, emailTitle, emailContent);
        customerService.addEmailSendHistory(companyId, false);

        return ResponseData.emptyResponse();
    }

    private void sendUsedOutTask(Company company, boolean email) throws Exception {
        //判断是否已经发送过了通知，如果没有发送则发送，发送过了则不再发送
        NoticeHistory noticeHistory = new NoticeHistory();
        noticeHistory.setCompanyId(company.getId());
        noticeHistory.setPlan(false);
        noticeHistory.setEmail(email);
        noticeHistory.setUsedOut(true);
        Optional<NoticeHistory> historyOptional = commonService.searchOneOptional(noticeHistory);

        //该计划已经发送过了
        if (!historyOptional.isPresent()) {
            logger.info("the out task not  send for company {}", company.getId());
            String content = new ZeroTimeSystemTask().unplannedNoticeTemplate(company.getName(), email, "接下來", "ran out");
            //没有发送过，那么发送一次
            EmailClient.getInstance().sendEmail(company.getEmail(), ZeroTimeSystemTask.UNPLANNED_EMAIL_TITLE, content);

            //添加已经发送完成的任务
            {
                NoticeHistory noticeHistoryNew = new NoticeHistory();
                noticeHistoryNew.setCompanyId(company.getId());
                noticeHistoryNew.setPlan(false);
                noticeHistoryNew.setEmail(email);
                noticeHistoryNew.setUsedOut(true);
                commonService.directSave(noticeHistoryNew);
            }
        } else {
            logger.info("has send the task");
        }
    }

    @ApiOperation(value = "验证码登录")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/random/code/login"), produces = ("application/json;charset=UTF-8"))
    public ResponseData randomCodeLogin(@RequestBody RandomLogin randomLogin) throws Exception {
        String emailOrPhone = randomLogin.getName();
        Long companyId = randomLogin.getCompanyId();
        VerifyUtil.isEmpty(emailOrPhone);
        String randomCode = customerService.getRandomFromCache(emailOrPhone);
        VerifyUtil.verify(() -> isNotEmpty(randomCode), RANDOM_CODE_EXPIRE);

        VerifyUtil.verify(() -> randomCode.equals(randomLogin.getCode()), RANDOM_CODE_WRONG);
        Customer customer = customerService.findCustomerByName(emailOrPhone, companyId);
        VerifyUtil.verify(() -> customer != null, USER_NOT_EXIST);
        customerService.isCustomerValid(customer);
        customerService.cleanRandomFromCache(emailOrPhone);

        ServletUtil.setCustomer(customer);
        return commonService.createResponse(customer);
    }

    @ApiOperation(value = "会员登录")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/login"), produces = ("application/json;charset=UTF-8"))
    public ResponseData login(@RequestBody Customer reqCustomer) throws Exception {
        String name = reqCustomer.getName();
        String password = reqCustomer.getPassword();
        Long companyId = reqCustomer.getCompanyId();
        VerifyUtil.isEmpty(name, password);
        VerifyUtil.verify(() -> companyId != null);

        Customer customerInDb = customerService.findCustomerByName(name, companyId);
        VerifyUtil.verify(() -> customerInDb != null, USER_NAME_OR_PASSWORD_WRONG);

        boolean login = customerService.login(customerInDb, reqCustomer);
        VerifyUtil.verify(() -> login, USER_NAME_OR_PASSWORD_WRONG);
        customerService.isCustomerValid(customerInDb);

        ServletUtil.setCustomer(customerInDb);

        return commonService.createResponse(customerInDb);
    }

    @ApiOperation(value = "会员注销")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/logout"), produces = ("application/json;charset=UTF-8"))
    public ResponseData logout() {
        ServletUtil.cleanCustomer();
        return ResponseData.emptyResponse();
    }

    @ApiOperation(value = "验证码校验， 参数是account和code")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/random/code/validate"), produces = ("application/json;charset=UTF-8"))
    public ResponseData validateRandomCode(@RequestBody RandomCode randomCode) throws ResponseStatusException {
        String account = randomCode.getAccount();
        String code = randomCode.getCode();
        VerifyUtil.isEmpty(account, code);
        String randomCodeInCache = customerService.getRandomFromCache(account);
        VerifyUtil.verify(() -> code.equals(randomCodeInCache), RANDOM_CODE_WRONG);

        //将当前会话设置成可以修改密码，也可以注册
        ServletUtil.setSessionAttribute(CUSTOMER_RANDOM_CODE_VALID, account);

        customerService.cleanRandomFromCache(account);

        return ResponseData.emptyResponse();
    }

    @ApiOperation(value = "判断账号是否存在,参数是name,带checkCustomerStatus检查会员账号的状态是否已经关停了，关停的账号也认为是账号不存在")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/exists"), produces = ("application/json;charset=UTF-8"))
    public ResponseData accountExist(@RequestBody Customer customer) throws Exception {
        String name = customer.getName();
        Long companyId = customer.getCompanyId();
        VerifyUtil.verify(() -> isNotEmpty(name));
        VerifyUtil.verify(() -> companyId != null);
        AccountExistResult accountExistResult = customerService.isAccountExist(name, customer.getCompanyId(), getBoolean(customer.getCheckCustomerStatus()));
        boolean accountExist = accountExistResult.isEmailExist() || accountExistResult.isPhoneExist();
        return commonService.createResponse(accountExist);
    }

    /**
     * 验证码校验过后，直接输入密码，所以这里一定要先校验难码是否已经校验通过了
     *
     * @param customer
     * @return
     * @throws ResponseStatusException
     */
    @ApiOperation(value = "注册,参数是name和password, companyId")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/register"), produces = ("application/json;charset=UTF-8"))
    public ResponseData register(@RequestBody Customer customer) throws Exception {
        String name = customer.getName();
        String password = customer.getPassword();
        Long companyId = customer.getCompanyId();
        VerifyUtil.isEmpty(name, password);
        VerifyUtil.verify(() -> companyId != null);
        companyService.findCompanyById(companyId);

        String validateAccount = ServletUtil.getSessionAttribute(CUSTOMER_RANDOM_CODE_VALID);
        VerifyUtil.verify(() -> validateAccount != null, RANDOM_CODE_EXPIRE);

        VerifyUtil.verify(() -> validateAccount.equals(name));
        String salt = Sha256Util.generateSalt();
        password = Sha256Util.sha256(password, salt);

        Customer customerSave = new Customer();
        customerSave.setPassword(password);
        customerSave.setSalt(salt);
        customerSave.setName(name);
        customerSave.setCompanyId(companyId);
        if (EmailValidator.getInstance().isValid(name)) {
            customerSave.setEmail(name);
        } else {
            customerSave.setPhone(name);
            String areaCode = JRedisUtil.getKV(PHONE_AREA_CODE + name);
            customerSave.setAreaCode(areaCode);
        }

        //创建二维码
        String qrCode = MongoId.generateId();
        customerSave.setQrCode(qrCode);

        //生成二维码文件
        customerService.generateQrCode(qrCode);
        customerSave.setQrCodeImg(qrCode + ".png");

        //清空凭证
        ServletUtil.cleanSessionAttribute(CUSTOMER_RANDOM_CODE_VALID);

        //设置会员的等级
        Optional<VipLevel> customerVipLevelOption = customerService.findCustomerVipLevel(0, customer.getCompanyId());
        if (customerVipLevelOption.isPresent()) {
            customerSave.setVipLevelId(customerVipLevelOption.get().getId());
        }

        commonService.createObject(customerSave);
        ServletUtil.setCustomer(customerSave);

        //送一次性的券
        customerService.addLevelTicketToCustomer(customerSave);

        return commonService.createResponse(customerSave);
    }

    @ApiOperation(value = "找回密码,或者找回密码, companyId一定要带")
    @MethodValidator(mustLogin = false)
    @PutMapping(value = ("/customer/reset/password"), produces = ("application/json;charset=UTF-8"))
    public ResponseData resetPassword(@RequestBody Customer customer) throws Exception {
        String name = customer.getName();
        String password = customer.getPassword();
        Long companyId = customer.getCompanyId();
        VerifyUtil.isEmpty(name, password);
        VerifyUtil.verify(() -> companyId != null);

        String validateAccount = ServletUtil.getSessionAttribute(CUSTOMER_RANDOM_CODE_VALID);
        VerifyUtil.verify(() -> validateAccount != null, RANDOM_CODE_EXPIRE);
        VerifyUtil.verify(() -> validateAccount.equals(name));
        Customer customerInDb = customerService.findCustomerByName(name, companyId);
        String salt = Sha256Util.generateSalt();
        password = Sha256Util.sha256(password, salt);
        customerInDb.setSalt(salt);
        customerInDb.setPassword(password);
        commonService.save(customerInDb);

        //清空凭证
        ServletUtil.cleanSessionAttribute(CUSTOMER_RANDOM_CODE_VALID);
        ServletUtil.setCustomer(customerInDb);
        return commonService.createResponse(customerInDb);
    }

    /**
     * 获取用户名
     *
     * @param customer
     * @return
     */
    public String getCustomerName(Customer customer) {
        if (isNotEmpty(customer.getPhone())) {
            return customer.getPhone();
        }

        return customer.getEmail();
    }

    @ApiOperation(value = "管理端创建会员账号")
    @PostMapping(value = ("/customer/create"), produces = ("application/json;charset=UTF-8"))
    public ResponseData createCustomer(@RequestBody Customer customer) throws Exception {
        Long companyId = customer.getCompanyId();
        companyService.findCompanyById(companyId);
        User user = ServletUtil.getUser();

        VerifyUtil.verify(() -> companyService.ownCompany(user, companyId));
        String name = getCustomerName(customer);
        VerifyUtil.isEmpty(name);
        customer.setName(name);

        //如果邮件没有传，强制设置成null
        if (isEmpty(customer.getEmail())) {
            customer.setEmail(null);
        }

        if (isEmpty(customer.getPhone())) {
            customer.setPhone(null);
        }

        //校验账号是否已经存在了
        AccountExistResult accountExist = customerService.isAccountExist(customer, companyId);
        if (accountExist.isPhoneExist() && accountExist.isEmailExist()) {
            VerifyUtil.throwError(EMAIL_AND_PHONE_REGISTER);
        }

        if (accountExist.isEmailExist()) {
            VerifyUtil.throwError(EMAIL_REGISTER);
        }

        if (accountExist.isPhoneExist()) {
            VerifyUtil.throwError(PHONE_REGISTER);
        }

        if (customer.getPassword() != null) {
            String salt = Sha256Util.generateSalt();
            String password = Sha256Util.sha256(customer.getPassword(), salt);
            customer.setPassword(password);
            customer.setSalt(salt);
        }

        //创建二维码
        String qrCode = MongoId.generateId();
        customer.setQrCode(qrCode);

        //生成二维码文件
        customerService.generateQrCode(qrCode);
        customer.setQrCodeImg(qrCode + ".png");

        long preference = intListToBitNumber(customer.getPreferenceList());
        customer.setPreference(preference);

        Optional<VipLevel> vipLevelOptional = customerService.findCustomerVipLevel(0, companyId);
        if (vipLevelOptional.isPresent()) {
            customer.setVipLevelId(vipLevelOptional.get().getId());
        }

        commonService.createObject(customer);

        if (customer.getVipLevelId() != null) {
            //送一次的券
            customerService.addLevelTicketToCustomer(customer);
        }

        return commonService.createResponse(customer);
    }

    @ApiOperation(value = "查询当前会员账号，带companyId查询")
    @PutMapping(value = ("/customer/info"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData getCurrentInfo(@RequestBody Customer reqCustomer) throws Exception {
        VerifyUtil.verify(() -> reqCustomer.getCompanyId() != null);
        Customer customer = ServletUtil.getCustomer();

        if (customer != null) {
            customerService.addCustomerLevelInfo(customer);

            if (customer.getVipEndTime() != null) {
                customer.setVipEndDate(DateUtil.format(customer.getVipEndTime(), "yyyy-MM-dd"));
            }

            return commonService.createResponse(customer);
        }

        return ResponseData.emptyResponse();
    }

    @ApiOperation(value = "查询会员账号")
    @PutMapping(value = ("/customer"), produces = ("application/json;charset=UTF-8"))
    public ResponseData findCustomer(@RequestBody Customer customer) throws Exception {
        customer.setSortField(new String[]{"createTime"});
        customer.setSortType("DESC");
        preSearch(customer);

        Optional<Customer> customerOptional = commonService.searchOneOptional((Customer) ClassUtil.clone(customer));
        if (customerOptional.isPresent()) {
            Customer customerInDb = customerOptional.get();
            Long companyId = customerInDb.getCompanyId();
            boolean ownCompany = companyService.ownCompany(companyId);
            VerifyUtil.verify(() -> ownCompany);
        }

        return commonService.searchResponse(customer, (c) -> {
            customerService.addCustomerLevelInfo(c);

            if (c.getVipEndTime() != null) {
                c.setVipEndDate(DateUtil.format(c.getVipEndTime(), "yyyy-MM-dd"));
            }
        });
    }

    private void preSearch(Customer customer) {
        //如果输入了年龄，那么按照时间来计算
        if (customer.getStartAge() != null) {
            customer.setEndAgeBirthDay(System.currentTimeMillis() - customer.getStartAge() * DateUtil.ONE_YEAR);
        }

        //结束年龄需要添加一岁
        if (customer.getEndAge() != null) {
            customer.setStartAgeBirthDay(System.currentTimeMillis() - (customer.getEndAge() + 1) * DateUtil.ONE_YEAR);
        }
    }

    @ApiOperation(value = "刪除会员账号，按照ID來刪除")
    @DeleteMapping(value = ("/customer"), produces = ("application/json;charset=UTF-8"))
    public ResponseData deleteCustomer(@RequestBody Customer customer) throws Exception {
        Long customerId = customer.getId();

        if (customerId != null) {
            Customer customerInDb = customerService.findCustomer(customerId);
            boolean ownCompany = companyService.ownCompany(customerInDb.getCompanyId());
            VerifyUtil.verify(() -> ownCompany);
        }

        return commonService.delete(customer);
    }

    @ApiOperation(value = "修改会员账号")
    @PutMapping(value = ("/customer/modify"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData modifyCustomer(@RequestBody Customer customer) throws Exception {
        //没有传电话号码，不处理
        if (isEmpty(customer.getPhone())) {
            customer.setPhone(null);
        }

        if (customer.id != null) {
            return privateModifyCustomer(customer);
        } else if (customer.ids != null) {
            List<Long> ids = customer.ids;
            customer.setIds(null);

            //循环更新
            for (Long id : ids) {
                customer.setId(id);
                privateModifyCustomer(customer);
            }

            return ResponseData.emptyResponse();
        } else {
            return ResponseData.emptyResponse();
        }
    }

    private ResponseData privateModifyCustomer(Customer customer) throws Exception {
        Long customerId = customer.getId();
        Customer customerInDb = customerService.findCustomer(customerId);

        if (!isNotEmpty(customerInDb.getScore())) {
            customerInDb.setScore(0);
        }
        if (!isNotEmpty(customerInDb.getScoreHistory())) {
            customerInDb.setScoreHistory(0);
        }

        Long companyId = customerInDb.getCompanyId();

        //名称不能修改
        customer.setName(null);

        //有公司权限的权限，那么可以随便操作
        if (companyService.ownCompany(customerInDb.getCompanyId())) {
            //空的操作先留在这里
            if (getBoolean(customerInDb.getRenewVip())) {
                //要增加VIP的时间了
            }

            //修改密码
            if (isNotEmpty(customer.getPassword())) {
                String salt = Sha256Util.generateSalt();
                String newPassword = Sha256Util.sha256(customer.getPassword(), salt);
                customer.setPassword(newPassword);
                customer.setSalt(salt);
            }

            //如果修改了不是会员，那么VIP到期时间清空
            if (customer.getVip() != null && !customer.getVip()) {
                customerInDb.setVipEndTime(null);
                commonService.save(customerInDb);
            } else if (customer.getVipEndTime() != null) {
                //如果修改了VIP的时间，那么用这一天的结束时间
                Long vipEndTime = customer.getVipEndTime();
                customer.setVipEndTime(DateUtil.endTimeInDay(vipEndTime));
            }

            //如果是修改了历史积分，那么修改等级
            if (customer.getScoreHistory() != null) {
                int scoreHistory = getInt(customer.getScoreHistory());
                Optional<VipLevel> customerVipLevelOptional = customerService.findCustomerVipLevel(scoreHistory, companyId);
                if (customerVipLevelOptional.isPresent()) {
                    customer.setVipLevelId(customerVipLevelOptional.get().getId());
                    customer.setLevelName_en(customerVipLevelOptional.get().getName_en());
                    customer.setLevelName_zh(customerVipLevelOptional.get().getName_zh());
                    commonService.updateObject(customer);
                } else {
                    logger.info("modify customer score history , but can not find the level id");
                }
            }


        } else {
            Customer currentCustomer = ServletUtil.getCustomer();

            //如果旧密码与新密码一起传过来，那就是修改密码
            if (isNotEmpty(customer.getOldPassword()) && isNotEmpty(customer.getPassword())) {
                customerService.customerModifySelfPassword(customer, customerInDb);
                return commonService.createResponse(customerInDb);
            }

            //自己修改自己，但是不相关的字段不能修改
            if (currentCustomer != null && equals(customer.getId(), customerId)) {
                for (Field field : Customer.class.getFields()) {
                    field.setAccessible(true);
                    CustomerNotModify annotation = field.getAnnotation(CustomerNotModify.class);
                    if (annotation != null) {
                        field.set(customer, null);
                    }
                }
            } else {
                //非法用户
                VerifyUtil.throwError(INVALID_PARAMETER);
            }
        }

        //如果修改了邮件，那么邮件要么为空，要么是当前账号拥有
        if (isNotEmpty(customer.getEmail())) {
            Customer customerByEmail = customerService.findCustomerByEmail(customer.getEmail(), companyId);
            VerifyUtil.verify(() -> customerByEmail == null || equals(customerByEmail.getId(), customerId), EMAIL_REGISTER);
        }

        //如果修改了电话，那么电话要么为空，要么是当前账号拥有
        if (isNotEmpty(customer.getPhone())) {
            Customer customerByPhone = customerService.findCustomerByPhone(customer.getPhone(), customer.getAreaCode(), companyId);
            VerifyUtil.verify(() -> customerByPhone == null || equals(customerByPhone.getId(), customerId), PHONE_REGISTER);
        }

        if (customer.getPreferenceList() != null) {
            long preference = intListToBitNumber(customer.getPreferenceList());
            customer.setPreference(preference);
        }

        ResponseData responseData = commonService.modifyObject(customer);

        //如果修改了积分，那么添加历史记录，并且重置账号等级
        if (customer.getScore() != null) {
            //修改的积分是否增加了，并且比累积的历史积分还要多
            Boolean scoreAdd = customer.getScore() > customerInDb.getScore() && customer.getScore() > customerInDb.getScoreHistory();

            ScoreHistory scoreHistory = new ScoreHistory();
            scoreHistory.setCustomerId(customerId);
            scoreHistory.setChangeType(SCORE_HISTORY_TYPE_MODIFY);
            scoreHistory.setValue(customer.getScore());
            commonService.createObject(scoreHistory);
            //重置会员等级并修改历史积分(积分增加了才重置，减少不重置)
            Optional<VipLevel> customerVipLevelOptional = customerService.findCustomerVipLevel(scoreHistory.getValue(), companyId);
            if (customerVipLevelOptional.isPresent() && scoreAdd) {

                customer.setScoreHistory(customer.getScore());
                customer.setVipLevelId(customerVipLevelOptional.get().getId());
                customer.setLevelName_en(customerVipLevelOptional.get().getName_en());
                customer.setLevelName_zh(customerVipLevelOptional.get().getName_zh());
                commonService.updateObject(customer);
            } else {
                logger.info("modify customer score history , but can not find the level id");
            }
        }

        //如果修改成了VIP，那么添加券
        if (getBoolean(customer.getVip())) {
            //给VIP用户送券
            customerService.addLevelTicketToCustomer(customerService.findCustomer(customer.getId()));
        }

        return responseData;
    }

    @ApiOperation(value = "查询会员系统的积分历史记录, customerId一定要传")
    @PutMapping(value = ("/score/history"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData scoreHistory(@RequestBody ScoreHistory scoreHistory) throws Exception {
        Long customerId = scoreHistory.getCustomerId();
        VerifyUtil.verify(() -> customerId != null);

        scoreHistory.setSortField(new String[]{"createTime"});
        scoreHistory.setSortType("DESC");

        return commonService.searchResponse(scoreHistory);
    }

    @ApiOperation(value = "查询会员的消费历史, customerId一定要传")
    @PutMapping(value = ("/customer/order/history"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData findCustomerOrder(@RequestBody CustomerOrder customerOrder) throws Exception {
        Long customerId = customerOrder.getCustomerId();
        VerifyUtil.verify(() -> customerId != null);

        User user = ServletUtil.getUser();
        if (user == null) {
            Long customerIdInSession = ServletUtil.getCustomerId();
            VerifyUtil.verify(() -> equals(customerId, customerIdInSession), USER_NOT_LOGIN);
        } else {
            Customer customer = customerService.findCustomer(customerId);
            boolean ownCompany = CompanyService.getInstance().ownCompany(user, customer.getCompanyId());
            VerifyUtil.verify(() -> ownCompany);
        }

        customerOrder.setSortField(new String[]{"createTime"});
        customerOrder.setSortType("DESC");

        return commonService.searchResponse(customerOrder, (order) -> {
            try {
                Long shopId = order.getShopId();
                Shop shop = shopService.findShopById(shopId);
                order.setShopName_zh(shop.getName_zh());
                order.setShopName_en(shop.getName_en());
            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    @ApiOperation(value = "查询会员的优惠卷")
    @PutMapping(value = ("/customer/ticket"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData findCustomerTicket(@RequestBody CustomerTicket customerTicket) throws Exception {
        Long customerId = customerTicket.getCustomerId();
        VerifyUtil.verify(() -> customerId != null);

        //如果是登录账号，可以随便查询
        Long userId = ServletUtil.getUserId();

        if (userId == null) {
            Long customerIdInSession = ServletUtil.getCustomerId();
            VerifyUtil.verify(() -> equals(customerIdInSession, customerId), USER_NOT_LOGIN);
        } else {
            //判断登录账号是否在所在餐厅
            User user = ServletUtil.getUser();
            Customer customer = customerService.findCustomer(customerId);
            boolean companyRelated = new Validator().companyRelated(customer.getCompanyId(), user);
            VerifyUtil.verify(() -> companyRelated, PRIVILEGE);
        }

        DiscountTicketService discountTicketService = DiscountTicketService.getInstance();

        return commonService.searchResponse(customerTicket, (customerTicketInDb) -> {
            try {
                Long ticketId = customerTicketInDb.getTicketId();
                DiscountTicket ticket = discountTicketService.findTicket(ticketId, true);

                customerTicketInDb.setTicketName_zh(discountTicketService.getTicketNameZh(ticket));
                customerTicketInDb.setTicketName_en(discountTicketService.getTicketNameEn(ticket));

                //没有使用过，然后已过期的优惠券
                if (!getBoolean(ticket.getUsed()) && System.currentTimeMillis() - getLong(customerTicketInDb.getExpiredTime()) > 0) {
                    customerTicketInDb.setExpired(true);
                    commonService.save(customerTicketInDb);
                    discountTicketService.setTicketToExpired(customerTicketInDb.getCode(), customerTicket.getCompanyId());
                } else {
                    customerTicketInDb.setExpired(false);
                }

                customerTicketInDb.setExpiredDate(DateUtil.formatDate(getLong(customerTicketInDb.getExpiredTime())));
                ticket.setExpiredTime(ticket.getEndTime());

                customerTicketInDb.setDiscountTicket(ticket);
            } catch (Exception e) {
                logger.error("e", e);
            }
        });
    }

    @ApiOperation(value = "会员兑换优惠券,传code和companyId")
    @PutMapping(value = ("/customer/ticket/exchange"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData exchangeTicket(@RequestBody DiscountTicket discountTicket) throws Exception {
        //必须要是一个已经登录的会员账号
        Long customerId = discountTicket.getCustomerId();
        String code = discountTicket.getCode();
        Long companyId = discountTicket.getCompanyId();
        VerifyUtil.verify(() -> code != null);
        VerifyUtil.verify(() -> companyId != null);
        VerifyUtil.verify(() -> customerId != null);
        Long customerIdInSession = ServletUtil.getCustomerId();
        VerifyUtil.verify(() -> equals(customerId, customerIdInSession), USER_NOT_LOGIN);

        DiscountTicketService discountTicketService = DiscountTicketService.getInstance();
        Optional<DiscountTicket> ticketOptional = discountTicketService.findTicket(code, companyId);
        VerifyUtil.verify(() -> ticketOptional.isPresent(), DISCOUNT_TICKET_NOT_EXIST);

        DiscountTicket discountTicketInDb = ticketOptional.get();

        VerifyUtil.verify(() -> !getBoolean(discountTicketInDb.getUsed()), DISCOUNT_TICKET_NOT_EXIST);

        //不能是线上券
        VerifyUtil.verify(() -> !getBoolean(discountTicketInDb.getOnlineTicket()), DISCOUNT_TICKET_NOT_EXIST);

        //不能是模板
        VerifyUtil.verify(() -> !getBoolean(discountTicketInDb.getTemplate()), DISCOUNT_TICKET_NOT_EXIST);

        //不能是已经存在某一个会员账号里面的
        Optional<CustomerTicket> customerTicketOptional = customerService.findCustomerTicketInCompany(companyId, code);

        if (customerTicketOptional.isPresent()) {
            CustomerTicket customerTicket = customerTicketOptional.get();
            if (equals(customerTicket.getCustomerId(), customerId)) {
                VerifyUtil.throwError(TICKET_EXCHANGE_SELF);
            } else {
                VerifyUtil.throwError(TICKET_EXCHANGE_BY_OTHERS);
            }
        }

        //必须要是生成的优惠券才可以
        VerifyUtil.verify(() -> getBoolean(discountTicketInDb.getCanExchange()), DISCOUNT_TICKET_NOT_EXIST);

        //添加绑定
        discountTicketInDb.setCustomerId(customerId);
        discountTicketInDb.setExchange(true);
        commonService.save(discountTicketInDb);

        //条件均满足，添加该优惠券到对应的会员账号里面
        CustomerTicket customerTicket = new CustomerTicket();
        customerTicket.setCompanyId(companyId);
        customerTicket.setCustomerId(customerId);
        customerTicket.setTicketId(discountTicketInDb.getId());
        customerTicket.setParentTicketId(discountTicketInDb.getParentId());
        customerTicket.setUsed(false);
        customerTicket.setExpiredTime(discountTicketInDb.getEndTime());
        customerTicket.setLimitNumber(false);
        customerTicket.setExpired(false);
        customerTicket.setCode(discountTicketInDb.getCode());

        //添加优惠券的信息
        customerTicket.setDiscountTicket(discountTicketInDb);
        ResponseData responseData = commonService.createObject(customerTicket);
        return responseData;
    }

    @ApiOperation(value = "当前订单，哪些优惠券可以使用,id是订单的ID，shopId,customerId,可选ticketCodeList")
    @PutMapping(value = ("/customer/available/ticket"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData availableTicketList(@RequestBody Order order) throws Exception {
        if (isNotEmpty(order.getTicketCodeList())) {
            List<DiscountTicket> discountTicketList = checkAvailableTicketList(order);
            Long shopId = order.getShopId();
            Company company = CompanyService.getInstance().findCompanyByShopId(shopId);

            HashMap<String, List<DiscountTicket>> resultList = new HashMap<>();
            resultList.put("ok", discountTicketList.stream().filter(p -> getBoolean(p.getCanUse())).collect(Collectors.toList()));


            List<DiscountTicket> failedList = new ArrayList<>();

            List<DiscountTicket> inputTicketList = order.getTicketCodeList().stream().map(code -> {
                Optional<DiscountTicket> ticketOptional = DiscountTicketService.getInstance().findTicket(code, company.getId());
                return ticketOptional;
            }).filter(p -> p.isPresent()).map(p -> p.get()).collect(Collectors.toList());

            failedList.addAll(inputTicketList);
            failedList.addAll(discountTicketList.stream().filter(p -> !getBoolean(p.getCanUse())).collect(Collectors.toList()));

            resultList.put("failed", failedList);
            return commonService.createResponse(resultList);
        }

        Long customerId = order.getCustomerId();
        Long orderId = order.getId();
        Long shopId = order.getShopId();

        VerifyUtil.verify(() -> customerId != null);
        VerifyUtil.verify(() -> orderId != null);
        VerifyUtil.verify(() -> shopId != null);

        List<DiscountTicket> customerTicketList;

        if (customerId == WAITER_LEADER_TICKET) {
            Shop shop = ShopService.getInstance().findShopById(shopId);
            customerTicketList = customerService.findWaiterLeaderTicketList(shop.getCompanyId());
        } else {
            customerTicketList = customerService.findCustomerTicketList(customerId);
            //处理已过期的优惠券
            for (DiscountTicket discountTicket : customerTicketList) {
                if (!getBoolean(discountTicket.getUsed()) && !getBoolean(discountTicket.getExpired()) && System.currentTimeMillis() - getLong(discountTicket.getExpiredTime()) > 0) {
                    Optional<CustomerTicket> customerTicketOptional = customerService.findCustomerTicket(customerId, discountTicket.getCode());
                    discountTicket.setExpired(true);
                    commonService.save(discountTicket);
                    if (customerTicketOptional.isPresent()) {
                        CustomerTicket customerTicket = customerTicketOptional.get();
                        customerTicket.setExpired(true);
                        commonService.save(customerTicket);

                        DiscountTicketService.getInstance().setTicketToExpired(customerTicket.getCode(), customerTicket.getCompanyId());
                    }
                }
            }

            //已使用，已过期的均不显示
            customerTicketList = customerTicketList.stream().filter(p -> !getBoolean(p.getUsed())).filter(p -> !getBoolean(p.getExpired())).collect(Collectors.toList());
        }

        Order calTicketOrder = getCalTicketOrder(order);

        List<DiscountTicket> okList = customerTicketList.stream().filter(ticket -> {
            return customerService.ticketSatisfyOrder(ticket, calTicketOrder);
        }).collect(Collectors.toList());

        //将符合要求的优惠券删掉
        customerTicketList.removeAll(okList);
        List<DiscountTicket> failedList = customerTicketList;


        HashMap<String, List<DiscountTicket>> resultList = new HashMap<>();
        resultList.put("ok", okList);
        resultList.put("failed", failedList);

        return commonService.createResponse(resultList);
    }

    /**
     * 获取计算优惠券的订单
     *
     * @param order
     * @return
     * @throws Exception
     */
    private Order getCalTicketOrder(Order order) throws Exception {
        OrderService orderService = OrderService.getInstance();
        Long shopId = order.getShopId();
        Long orderId = order.getId();
        Order orderInDb = orderService.findOrder(shopId, orderId);

        //子订单的价格都是已经计算好的
        if (getBoolean(orderInDb.getSubOrder())) {
            return (Order) ClassUtil.clone(orderInDb);
        }

        if (isEmpty(order.getOrderItemDetailList())) {
            //添加传过来的优惠券的CODE
            orderInDb.setTicketCodeList(order.getTicketCodeList());

            //分钱结账
            if (order.getUserCost() != null) {
                orderInDb.setCostOrigin(order.getUserCost());
            } else if (order.getCostOrigin() != null) {
                orderInDb.setCostOrigin(order.getCostOrigin());
            }

            return orderInDb;
        } else {
            orderService.calPrice(order);
            //复制场景，复制订单类型
            order.setOrderType(orderInDb.getOrderType());
            order.setSceneId(orderInDb.getSceneId());
            return order;
        }
    }

    @ApiOperation(value = "检查哪些使用了当前优惠券之后，哪些优惠券还可以使用,id是订单的ID，shopId,customerId,ticketCodeList,")
    @PutMapping(value = ("/customer/check/ticket/list"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData checkTicketList(@RequestBody Order order) throws Exception {
        List<DiscountTicket> customerTicketList = checkAvailableTicketList(order);

        return commonService.createResponse(customerTicketList);
    }

    /**
     * 传优惠券过来后，判断哪些优惠券还可以使用
     *
     * @param order
     * @return
     * @throws Exception
     */
    private List<DiscountTicket> checkAvailableTicketList(Order order) throws Exception {
        Long orderId = order.getId();
        Long shopId = order.getShopId();
        Long customerId = order.getCustomerId();
        VerifyUtil.isEmpty(orderId, shopId, customerId);
        OrderService orderService = OrderService.getInstance();

        List<String> ticketCodeList = getList(order.getTicketCodeList());
        Order calTicketOrder = getCalTicketOrder(order);

        List<DiscountTicket> customerTicketList;
        if (customerId == WAITER_LEADER_TICKET) {
            Shop shop = ShopService.getInstance().findShopById(shopId);
            customerTicketList = customerService.findWaiterLeaderTicketList(shop.getCompanyId());
        } else {
            customerTicketList = customerService.findCustomerTicketList(customerId);
        }

        //将已经传过来的优惠券从判断列表中移除
        customerTicketList = customerTicketList.stream().filter(ticket -> !ticketCodeList.contains(ticket.getCode())).collect(Collectors.toList());
        boolean subOrder = getBoolean(calTicketOrder.getSubOrder());

        //过滤出符合当前订单的优惠券
        customerTicketList = customerTicketList.stream().filter(ticket -> {
            return customerService.ticketSatisfyOrder(ticket, calTicketOrder);
        }).collect(Collectors.toList());

        //依次判断每一个优惠券是否还可以使用
        for (DiscountTicket discountTicket : customerTicketList) {
            Order cloneOrder = (Order) ClassUtil.clone(calTicketOrder);
            cloneOrder.setCustomerId(customerId);
            List<String> codeList = new ArrayList<>();
            codeList.addAll(ticketCodeList);
            codeList.add(discountTicket.getCode());
            cloneOrder.setTicketCodeList(codeList);

            //子订单不用重新计算小计
            PriceResult priceResult = orderService.calPrice(cloneOrder, subOrder);
            Optional<TicketResult> ticketResultOptional = priceResult.getResultList().stream().filter(result -> result.getCode().equals(discountTicket.getCode())).findAny();
            //只要在错误列表里面没有找到，并且在可使用时间范围内的，那么就是可以使用的
            discountTicket.setCanUse((!ticketResultOptional.isPresent() || isEmpty(ticketResultOptional.get().getMsg())) && getLong(discountTicket.getStartTime()) < System.currentTimeMillis());
        }
        return customerTicketList;
    }

    /**
     * 會員數據導出
     *
     * @param customer
     * @return
     */
    @ApiOperation(value = "会员系统数据导出，传入参数与查询保持一致")
    @PutMapping(value = ("/customer/export"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData exportData(@RequestBody Customer customer) throws Exception {
        preSearch(customer);
        File file = customerService.exportData(customer);
        return commonService.createResponse(file.getName());
    }

    @ApiOperation(value = "查询生日邮件模板")
    @PutMapping(value = ("/birthday/template"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData findBirthdayTemplate(@RequestBody MarketBirthdayTemplate marketBirthdayTemplate) throws Exception {
        Long companyId = marketBirthdayTemplate.getCompanyId();

        if (companyId != null) {
            MarketBirthdayTemplate birthdayTemplate = customerService.findBirthdayTemplate(companyId);
            List<DiscountTicket> ticketList = getTicketList(birthdayTemplate.getTicketAndLimitList());
            birthdayTemplate.setTicketList(ticketList);
            return commonService.createResponse(birthdayTemplate);
        }

        return commonService.searchResponse(marketBirthdayTemplate);
    }

    @ApiOperation(value = "修改生日邮件模板")
    @PutMapping(value = ("/birthday/template/modify"), produces = ("application/json;charset=UTF-8"))
    public ResponseData modifyBirthdayTemplate(@RequestBody MarketBirthdayTemplate marketBirthdayTemplate) throws Exception {
        return commonService.updateObject(marketBirthdayTemplate);
    }

    @ApiOperation(value = "创建营销模板")
    @PostMapping(value = ("/market/email/template"), produces = ("application/json;charset=UTF-8"))
    public ResponseData createMarketEmailTemplate(@RequestBody MarketEmailTemplate marketEmailTemplate) throws Exception {
        companyService.findCompanyById(marketEmailTemplate.getCompanyId());
        companyService.ownCompany(marketEmailTemplate.getCompanyId());
        return commonService.createObject(marketEmailTemplate);
    }

    @ApiOperation(value = "修改营销模板")
    @PutMapping(value = ("/market/email/template/modify"), produces = ("application/json;charset=UTF-8"))
    public ResponseData modifyMarketEmailTemplate(@RequestBody MarketEmailTemplate marketEmailTemplate) throws Exception {
        boolean ownCompany = companyService.ownCompany(commonService.findEntity(marketEmailTemplate.getId(), MarketEmailTemplate.class));
        VerifyUtil.verify(() -> ownCompany);
        return commonService.modifyObject(marketEmailTemplate);
    }

    @ApiOperation(value = "删除营销模板")
    @DeleteMapping(value = ("/market/email/template"), produces = ("application/json;charset=UTF-8"))
    public ResponseData deleteMarketEmailTemplate(@RequestBody MarketEmailTemplate marketEmailTemplate) throws Exception {
        boolean ownCompany = companyService.ownCompany(marketEmailTemplate);
        VerifyUtil.verify(() -> ownCompany);
        return commonService.delete(marketEmailTemplate);
    }

    @ApiOperation(value = "查询营销模板")
    @PutMapping(value = ("/market/email/template"), produces = ("application/json;charset=UTF-8"))
    public ResponseData findMarketEmailTemplate(@RequestBody MarketEmailTemplate marketEmailTemplate) throws Exception {
        return commonService.searchResponse(marketEmailTemplate);
    }

    @ApiOperation(value = "创建营销任务")
    @PostMapping(value = ("/market/marketTask"), produces = ("application/json;charset=UTF-8"))
    public ResponseData createMarketTask(@RequestBody MarketTask marketTask) throws Exception {
        companyService.findCompanyById(marketTask.getCompanyId());
        companyService.ownCompany(marketTask.getCompanyId());

        //发送方式允许为空，这样只是发送优惠券
        //VerifyUtil.verify(() -> getBoolean(marketTask.getSms()) || getBoolean(marketTask.getEmail()));
        //配送时间不能为空
        VerifyUtil.verify(() -> marketTask.getPeriodTimeConfig() != null);

        //添加通用名称
        ZhEnService.getInstance().dealZhEn(marketTask);

        customerService.dealMarketTaskDefaultValue(marketTask);
        VerifyUtil.verify(() -> isNotEmpty(marketTask.getCustomerList()));

        //保存实际的人数的ID，以及邮件人数，电话号码人数
        Map<String, Object> customerIdMap = customerService.calTaskUser(marketTask);
        marketTask.setCustomerIdList(new ArrayList<Long>((Set) customerIdMap.get("customerIdList")));
        marketTask.setEmailUserCount(((Number) customerIdMap.get("emailNumber")).longValue());
        marketTask.setPhoneUserCount(((Number) customerIdMap.get("phoneNumber")).longValue());
        marketTask.setRealNumber(((Number) customerIdMap.get("realNumber")).intValue());
        marketTask.setTotalNumber(((Number) customerIdMap.get("totalNumber")).longValue());

        //如果是立即发送
        PeriodTimeConfig periodTimeConfig = marketTask.getPeriodTimeConfig();
        VerifyUtil.verify(() -> periodTimeConfig != null);

        //只要不是一次性发送的任务，均作为周期性任务处理
        if (!getBoolean(periodTimeConfig.getOnce())) {
            marketTask.setPeriodTask(true);
        }

        ResponseData responseData = commonService.createObject(marketTask);

        //立即发送
        if (getBoolean(periodTimeConfig.getNowTime())) {
            customerService.executeMarketTask(marketTask);
        }

        return responseData;
    }

    @ApiOperation(value = "查询任务的实际人数")
    @PutMapping(value = ("/cal/task/real/number"), produces = ("application/json;charset=UTF-8"))
    public ResponseData calTaskUser(@RequestBody MarketTask marketTask) throws Exception {
        Map<String, Object> resultMap = customerService.calTaskUser(marketTask);
        resultMap.remove("customerIdList");
        return commonService.createResponse(resultMap);
    }

    @ApiOperation(value = "修改营销任务")
    @PutMapping(value = ("/market/marketTask/modify"), produces = ("application/json;charset=UTF-8"))
    public ResponseData modifyMarketTask(@RequestBody MarketTask marketTask) throws Exception {
        Optional<MarketTask> marketTaskOptional = customerService.findMarketTask(marketTask.getId());
        VerifyUtil.verify(() -> marketTaskOptional.isPresent());
        boolean ownCompany = companyService.ownCompany(marketTaskOptional.get().getCompanyId());
        VerifyUtil.verify(() -> ownCompany);

        ClassUtil.getAllField(marketTask).forEach(field -> {
            try {
                if (field.getAnnotation(CustomerNotModify.class) != null) {
                    field.set(marketTask, null);
                }
            } catch (Exception e) {
                logger.info("e", e);
            }
        });

        return commonService.modifyObject(marketTask);
    }

    @ApiOperation(value = "删除营销任务")
    @DeleteMapping(value = ("/market/marketTask"), produces = ("application/json;charset=UTF-8"))
    public ResponseData deleteMarketTask(@RequestBody MarketTask marketTask) throws Exception {
        boolean ownCompany = companyService.ownCompany(marketTask);
        VerifyUtil.verify(() -> ownCompany);

        Optional<MarketTask> taskOptional = customerService.findMarketTask(marketTask.getId());
        VerifyUtil.verify(() -> getBoolean(getInt(taskOptional.get().getStatus()) == MARKET_TASK_STATUS_STOP), TASK_NOT_STOP);

        return commonService.delete(marketTask);
    }

    @ApiOperation(value = "查询营销任务,如果是定时任务，那么添加periodTask为true查询")
    @PutMapping(value = ("/market/marketTask"), produces = ("application/json;charset=UTF-8"))
    public ResponseData findMarketTask(@RequestBody MarketTask marketTask) throws Exception {
        return commonService.searchResponse(marketTask, (task) -> {
            //如果使用了优惠券，那么将相关的优惠券查询并返回
            if (isNotEmpty(task.getTicketAndLimitList())) {
                List<DiscountTicket> ticketList = getTicketList(task.getTicketAndLimitList());
                task.setTicketList(ticketList);
            }
        });
    }

    private List<DiscountTicket> getTicketList(List<TicketAndLimit> ticketAndLimitList) {
        List<DiscountTicket> ticketList = getList(ticketAndLimitList).stream().map(ticketAndLimit -> {
            try {
                DiscountTicket discountTicket = DiscountTicketService.getInstance().findTicket(ticketAndLimit.getTicketId(), true);

                if (discountTicket != null) {
                    discountTicket.setLimitNumber(ticketAndLimit.getLimitNumber());
                    discountTicket.setTicketNumber(ticketAndLimit.getTicketNumber());
                }

                return discountTicket;
            } catch (Exception e) {
                logger.error("e", e);
                return null;
            }
        }).filter(p -> p != null).collect(Collectors.toList());
        return ticketList;
    }

    @ApiOperation(value = "查询营销任务历史记录")
    @PutMapping(value = ("/market/history"), produces = ("application/json;charset=UTF-8"))
    public ResponseData findMarketHistory(@RequestBody MarketHistory marketHistory) throws Exception {
        marketHistory.setSortType("DESC");
        marketHistory.setSortField(new String[]{"createTime"});

        return commonService.searchResponse(marketHistory);
    }

    @ApiOperation(value = "会员报告查询")
    @PutMapping(value = ("/customer/report"), produces = ("application/json;charset=UTF-8"))
    public ResponseData customerReport(@RequestBody Customer customer) throws Exception {
        Long companyId = customer.getCompanyId();
        VerifyUtil.verify(() -> companyId != null);
        boolean own = companyService.ownCompany(companyId);
        VerifyUtil.verify(() -> own);

        return ResponseData.emptyResponse();
    }

    /**
     * @param marketTask
     * @return
     */
    @ApiOperation(value = "计算每一种短信类型实际需要多少条短信")
    @PutMapping(value = ("/customer/cal/sms/count"), produces = ("application/json;charset=UTF-8"))
    public ResponseData calSmsCount(@RequestBody MarketTask marketTask) throws Exception {
        //计算每种优惠券实际需要的条数，如果有多条优惠券，那么将多条优惠券需要的条数相加
        List<TicketAndLimit> ticketAndLimitList = getList(marketTask.getTicketAndLimitList());
        if (isEmpty(ticketAndLimitList)) {
            logger.info("ticketAndLimitList is empty");
            return ResponseData.emptyResponse();
        }

        VerifyUtil.verify(() -> marketTask.getCompanyId() != null);

        //开始计算
        List<SmsCount> smsCountList = customerService.calSmsCount(marketTask);
        return commonService.createResponse(smsCountList);
    }

    @ApiOperation(value = "导入会员信息")
    @PostMapping(value = ("/customer/import"), produces = ("application/json;charset=UTF-8"))
    public ResponseData importCustomer(@RequestParam MultipartFile file, @RequestParam Long companyId) throws Exception {
        VerifyUtil.verify(() -> companyId != null);
        VerifyUtil.verify(() -> isNotEmpty(file));
        InputStream inputStream = file.getInputStream();
        ExcelUtil.getInstance().importExcel(inputStream, companyId);
        return ResponseData.emptyResponse();
    }

    @ApiOperation(value = "优惠券信息导入")
    @PostMapping(value = ("/customer/import/vouchers"), produces = ("application/json;charset=UTF-8"))
    public ResponseData importVouchers(@RequestParam MultipartFile file, @RequestParam Long ticketId) throws Exception {
        VerifyUtil.verify(() -> isNotEmpty(file));
        InputStream inputStream = file.getInputStream();
        ExcelUtil.getInstance().importVoucherExcel(inputStream, ticketId);
        return ResponseData.emptyResponse();
    }


//    @ApiOperation(value = "发送邮件测试接口")
//    @PutMapping(value = ("/test/ls/send"), produces = ("application/json;charset=UTF-8"))
//    public ResponseData testls(@RequestBody MarketTask marketTask) throws Exception {
//        Long id = marketTask.getId();
//        MarketTask marketTaskInDb = new MarketTask();
//        marketTaskInDb.setId(id);
//        marketTaskInDb.setCompanyId(117l);
//        MarketTask marketTask1 = commonService.searchOne(marketTaskInDb);
//        customerService.executeMarketTask(marketTask1);
//
//        return ResponseData.emptyResponse();
//    }


}
